package br.com.jbssistemas.dirfweb.daos;

import br.com.jbssistemas.dirfweb.hibernate.HibernateUtil;
import java.io.Serializable;
import java.util.List;
import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.transform.AliasToBeanResultTransformer;

/**
 *
 * @author daniel
 * @param <T>
 *
 */
public class DAOGenerico<T> implements Serializable {

    private Class<T> entityClass;

    public DAOGenerico(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    public void salvar(T entity) throws Exception {
        
        Session session = HibernateUtil.getSession();

        Transaction transaction = session.beginTransaction();

        session.save(entity);

        transaction.commit();

        session.close();

    }

    public void atualizar(T entity) throws Exception {

        Session session = HibernateUtil.getSession();

        Transaction transaction = session.beginTransaction();

        session.update(entity);

        transaction.commit();

        session.close();

    }

    public void salvarOuAtualizar(T entity) throws Exception {

        Session session = HibernateUtil.getSession();

        Transaction transaction = session.beginTransaction();

        session.saveOrUpdate(entity);

        transaction.commit();

        session.close();

    }

    public void excluir(T entity) throws Exception {

        Session session = HibernateUtil.getSession();

        Transaction transaction = session.beginTransaction();

        session.delete(entity);

        transaction.commit();

        session.close();

    }

    public T getById(Serializable id) throws Exception {

        Session ses = HibernateUtil.getSession();

        ses.setCacheMode(CacheMode.IGNORE);

        Serializable toReturn = (Serializable) ses.get(entityClass, id);

        ses.close();

        return (T) toReturn;
    }

    public <T extends Serializable> T getPojoCriterio(String query, Object... params) throws Exception {

        Session ses = HibernateUtil.getSession();

        ses.setCacheMode(CacheMode.IGNORE);

        org.hibernate.Query qr = ses.createQuery(query);

        qr.setMaxResults(1);

        for (int i = 0; i < params.length; i++) {
            qr.setParameter(i, params[i]);
        }

        Serializable toReturn = (Serializable) qr.uniqueResult();

        ses.close();

        return (T) toReturn;
    }

    public List<T> listar() throws Exception {

        Session session = HibernateUtil.getSession();

        Criteria criteria = session.createCriteria(entityClass);

        criteria.addOrder(Order.asc("id"));

        List<T> list = criteria.list();

        session.close();

        return list;

    }

    protected <T extends Serializable> List<T> listar(Class clazz, String... campos) throws Exception {

        Session session = HibernateUtil.getSession();

        Criteria criteria = session.createCriteria(clazz, "clazz");

        ProjectionList projectionList = Projections.projectionList();

        for (String campo : campos) {
            projectionList.add(Projections.property("clazz." + campo).as(campo));
        }

        List<T> toReturn = criteria.setProjection(projectionList)
                .setResultTransformer(new AliasToBeanResultTransformer(clazz))
                .list();
        
        session.close();
        
        return toReturn;

    }

    protected <T extends Serializable> List<T> listar(String query, Object... params) throws Exception {

        Session session = HibernateUtil.getSession();

        session.setCacheMode(CacheMode.IGNORE);

        org.hibernate.Query qr = session.createQuery(query);

        for (int i = 0; i < params.length; i++) {
            qr.setParameter(i, params[i]);
        }

        List<T> list = qr.list();

        session.close();

        return list;

    }

    protected <T extends Serializable> List<T> getPojos(int startingAt, int maxPerPage, String query, Object... params) {
        
        Session session = HibernateUtil.getSession();

        Transaction transaction = session.beginTransaction();

        Query qr = session.createQuery(query);

        qr.setFirstResult(startingAt);

        qr.setMaxResults(maxPerPage);

        for (int i = 0; i < params.length; i++) {
            qr.setParameter(i, params[i]);
        }
        List<T> retorno = qr.list();

        transaction.commit();

        session.close();

        return (List<T>) retorno;

    }

}
